package com.woodws.util;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * Created by maochao on 2015/11/13.
 */
public class FieldUtil {

    public static <C extends Object, A extends Annotation> Field getField(Class<C> type, Class<A> annotationClass) {
        if (type == Object.class) {
            return null;
        }

        Field[] fields = type.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            if (field.isAnnotationPresent(annotationClass)) {
                return field;
            }
        }
        return getField(type.getSuperclass(), annotationClass);
    }

    public static <R, A extends Annotation> R getValue(Object object, Class<A> annotationClass) {
        Field field = getField(object.getClass(), annotationClass);
        if (field == null) {
            return null;
        } else {
            try {
                field.setAccessible(true);
                return (R) field.get(object);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static <O> O getValue(Object object, String attr) {
        Object value = null;
        try {
            Class c = object.getClass();
            PropertyDescriptor pd = new PropertyDescriptor(attr, c);
            Method getMethod = pd.getReadMethod();
            value = getMethod.invoke(object);
        } catch (IntrospectionException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        return (O) value;
    }

    public static void setValue(Object object, String attr,Object value) {
        try {
            Class c = object.getClass();
            PropertyDescriptor pd = new PropertyDescriptor(attr, c);
            Method setMethod = pd.getWriteMethod();
            setMethod.invoke(object,value);
        } catch (IntrospectionException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}
